/*
|-----------------------------------------------------------------------------|
| Overall ANTLR Grammar File Structure                                        |
|-----------------------------------------------------------------------------|
| «grammarType» grammar name;
|   «optionsSpec»     = options { ... }
|   «tokensSpec»      = tokens { ... }
|   «attributeScopes» = «@action-scope-name::action-name» { ... }
|   «actions»
|   // rules
|   rule1 : ... ;
|   rule2 : ... ;
|   ...
|_____________________________________________________________________________|
|   «grammarType»         = ( lexer | parser | tree | <empty> )
|   «optionsSpec»         = options { ... }
|   «tokensSpec»          = tokens { ... }
|   «attributeScopes»     = 
|   «actions»             = @«action-scope-name»::«action-name» { ... }
|    «action-scope-name» = ( lexer | parser | tree | <empty> = parser )
|    «action-name»       = ( header | members | rulecatch | synpredgate )
|-----------------------------------------------------------------------------|
*/
/**
 * @asignatura: Procesadores de Lenguajes.
 * @autor:      Anthony Vittorio Russo Cabrera
 * @curso:      2012/2013
 * @práctica:   06 - ANTLR. Ambigüedades Sintácticas
 *
 * Referencias:
 *  - http://www.antlr.org/download/examples-v3.tar.gz
 *  |-> examples-v3/java/ANTLR/ANTLRv3.g
 *    
 */
parser grammar ANTLRv3Parser;

  options {
	  language = Java;
	  output = AST;
	  backtrack = true;
	  tokenVocab = ANTLRv3Lexer;
  }// options

  @parser::header {
    package pl.p06.antlr3;
  }//header
  @parser::members {
  }// members

//= Grammar Rules ANTLRv3 ====================================================|
grammarDef
  : (Lexer|Parser|Tree)? Grammar Identifier SemiColon
    (optionsSpec)?
    (tokensSpec)?
    (attrScope)*
    (action)*
    (rule { /* Comentar para hacer el test
            System.out.println("rule found : " + $rule::name);
            // para evitar el error:
            // java.util.EmptyStackException
            // ya que el testsuite no interpreta java */
          }
    )+
  ;

	tokensSpec
	  : Tokens_ LeftBracket (tokenSpec)+ RightBracket
	  ;
	
	tokenSpec
	  : Identifier (Assing CharacterLiteral)? SemiColon
	  ;
	
	attrScope
	  : Scope Identifier
	  ;
	
	action
	  : AtSign (actionScopeName DoubleColon)? Identifier
	  ;
	
		actionScopeName
		  : Identifier
		  | Lexer
		  | Parser
		  ;
	
	optionsSpec
	  : Options LeftBracket (option SemiColon)+ RightBracket
	  ;
	
		option
		    :   Identifier Assing optionValue
		  ;
		  
			optionValue
			    : Identifier
			    | StringLiteral
			    | CharacterLiteral
			    | DecimalLiteral
			    | Asterisk // used for k=*
			    | True
			    | False
			    ;
	
	rule
	scope {
	  String name;
	}
	  : ( modifier=(Protected|Public|Private|Fragment) )?
	    Identifier {$rule::name = $Identifier.text;}
	    (optionsSpec)?
	    Colon altList (compound_statement)? SemiColon
	  ;
	
		altList
		  : altpair (Stick altpair)*
		  ;
		
			altpair
			    : (element)+
			    ;
			
				element
				  : atom
				  | ebnf
				  ;
				
					atom
					  : range
					  | StringLiteral
					  | Identifier
					  ;
					
					ebnf
					  : block
					    ( Question
					    | Asterisk
					    | Plus
					    | SyntaxPred
					    )?
					  ;
					
						block
						    : LeftParenthesis
						      ((optionsSpec)? Colon )?
						      altList
						      RightParenthesis
						    ;
	
	
	range
	  : CharLiteral Range CharLiteral
	  ;
	
	//= Grammar Rules C ==========================================================|
	//-----------------------------------------------------------------------------
	// F u n c t i o n s
	
	  function_invocation returns [String name]
	  @init {
	    $name=null; // for now you must init here rather than in 'returns'
	  }
	    : Identifier LeftParenthesis ( argument_expression_list )? RightParenthesis
	    { $name = $Identifier.text; }
	    ;
	  
	    argument_expression_list
	      : conditional_expression (Comma conditional_expression)*
	      ;
	
	//-----------------------------------------------------------------------------
	// E x p r e s s i o n s
	expression
	  : assignment_expression (Comma assignment_expression)*
	  ;
	
	  assignment_expression
	    : lvalue assignment_operator assignment_expression
	    | conditional_expression
	    | function_invocation
	    ;
	
	    lvalue
	      : unary_expression
	      ;
	
	    assignment_operator
	      : Assing
	      | MultiplyEqual
	      | DivideEqual
	      | ModEqual
	      | AddEqual
	      | SubEqual
	      | LeftShiftEqual
	      | RightShiftEqual
	      | AndEqual
	      | ExpEqual
	      | OrEqual
	      ;
	
	    conditional_expression
	      : logical_or_expression (Question expression Colon conditional_expression)?
	      ;
	
	      logical_or_expression
	        : logical_and_expression (Or logical_and_expression)*
	        ;
	
	        logical_and_expression
	          : equality_expression (And equality_expression)*
	          ;
	
	          equality_expression
	            : relational_expression ((Equal|NotEqual) relational_expression)*
	            ;
	
	            relational_expression
	              : additive_expression ( ( Less | Greater | LessEqual | GreaterEqual ) additive_expression )*
	              ;
	
	              additive_expression
	                : (multiplicative_expression) (Plus multiplicative_expression | Minus multiplicative_expression)*
	                ;
	
	                multiplicative_expression
	                  : (cast_expression) (Asterisk cast_expression | Slash cast_expression | Percent cast_expression)*
	                  ;
	
	                  cast_expression
	                    : unary_expression
	                    //| LeftParenthesis type_name RightParenthesis cast_expression
	                    ;
	
	                    unary_expression
	                      : postfix_expression
	                      | unary_operator unary_expression
	                      ;
	
	                      unary_operator
	                        : Not
	                        | Increase
	                        | Decrease
	                        ;
	
	                      postfix_expression
	                        :   primary_expression
	                              ( LeftSquareBracket expression RightSquareBracket
	                              | Dot Identifier
	                              )*
	                        ;
	
	                        primary_expression
	                          : Identifier
	                          | constant
	                          | LeftParenthesis expression RightParenthesis
	                          ;
	
	                          constant
	                              : HexLiteral
	                              | OctalLiteral
	                              | DecimalLiteral
	                              | CharacterLiteral
	                              | StringLiteral
	                              | FloatingPointLiteral
	                              | True
	                              | False
	                              ;
	//-----------------------------------------------------------------------------
	// S t a t e m e n t s
	
	compound_statement
	  : LeftBracket
	      ( statement_list )?
	    RightBracket
	  ;
	
	statement_list
	  : ( statement )+
	  ;
	
	statement
	  : labeled_statement
	  | compound_statement
	  | expression_statement
	  | selection_statement
	  | iteration_statement
	  | jump_statement
	  ;
	
	  labeled_statement
	    : Case conditional_expression Colon statement
	    | Default Colon statement
	    ;
	
	  expression_statement
	    : SemiColon
	    | expression SemiColon
	    ;
	
	  selection_statement
	    : if_statement
	    | switch_statement
	    ;
	
	    if_statement
	      : If LeftParenthesis expression RightParenthesis statement (options {k=1; backtrack=false;}: Else statement)?
	      ;
	
	    switch_statement
	      : Switch LeftParenthesis expression RightParenthesis statement
	      ;
	
	  iteration_statement
	    : while_statement
	    | do_while_statement
	    | for_statement
	    ;
	
	    for_statement
	      : For LeftParenthesis expression_statement SemiColon expression_statement SemiColon expression? RightParenthesis statement        
	      ;
	
	    while_statement
	      : While LeftParenthesis expression RightParenthesis statement
	      ;
	
	    do_while_statement
	      : Do statement While LeftParenthesis expression RightParenthesis SemiColon
	      ;
	
	  jump_statement
	    : Goto Identifier SemiColon
	    | Continue SemiColon
	    | Break SemiColon
	    | Return SemiColon
	    | Return expression SemiColon
	    ;